Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


vendor/lxmfy/lxmfy/cli.py dev (c9f60cc5) Text, 25.38 KB

T8b949e"""CLI module for LXMFy bot framework.

Provides an interactive and colorful command-line interface for creating and managing LXMF bots,
including bot file creation and example cog generation.
"""

Tff7b72import T7ee787argparse
Tff7b72import T7ee787os
Tff7b72import T7ee787re
Tff7b72import T7ee787sys

Tff7b72from T7ee787.T7ee787__version__ Tff7b72import Te6edf3__version__
Tff7b72from T7ee787.T7ee787colors Tff7b72import Tb4b4b4(
Te6edf3ColorsTb4b4b4,
Te6edf3init_colorsTb4b4b4,
Te6edf3print_errorTb4b4b4,
Te6edf3print_headerTb4b4b4,
Te6edf3print_infoTb4b4b4,
Te6edf3print_menuTb4b4b4,
Te6edf3print_successTb4b4b4,
Te6edf3print_warningTb4b4b4,
Tb4b4b4)
Tff7b72from T7ee787.T7ee787templates Tff7b72import Te6edf3CogTestBotTb4b4b4, Te6edf3EchoBotTb4b4b4, Te6edf3NoteBotTb4b4b4, Te6edf3ReminderBotTb4b4b4, Te6edf3RRCBot


Tff7b72def Td2a8ffget_user_choiceTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Get user's choice from the menu."""
Tff7b72while Tff7b72TrueTb4b4b4:
Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3choice Tff7b72= Tffa657inputTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffEnter your choice (1-3): Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3choice Tff7b72= Tffa657inputTb4b4b4(Ta5d6ff"Ta5d6ffEnter your choice (1-3): Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3choice Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff2Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff3Ta5d6ff"Tb4b4b4]Tb4b4b4:
Tff7b72return Te6edf3choice
Te6edf3print_errorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid choice. Please enter a number between 1 and 3.Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffget_bot_nameTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Get bot name from user input."""
Tff7b72while Tff7b72TrueTb4b4b4:
Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3name Tff7b72= Tffa657inputTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffEnter bot name: Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3name Tff7b72= Tffa657inputTb4b4b4(Ta5d6ff"Ta5d6ffEnter bot name: Ta5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72return Te6edf3validate_bot_nameTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72except Tf85149ValueError Tff7b72as Te6edf3veTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInvalid bot name: Tffd700{Te6edf3veTffd700}Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffget_template_choiceTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Get template choice from user input."""
Te6edf3templates Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffbasicTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcogtestTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrrcTa5d6ff"Tb4b4b4]
Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Tffea00\nTffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffAvailable templates:Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3iTb4b4b4, Te6edf3template Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3templatesTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3ColorsTff7b72.Td2a8ffBOLDTffd700}Tffd700{Te6edf3iTffd700}Ta5d6ff.Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff Tffd700{Te6edf3templateTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffAvailable templates:Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3iTb4b4b4, Te6edf3template Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3templatesTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3iTffd700}Ta5d6ff. Tffd700{Te6edf3templateTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72while Tff7b72TrueTb4b4b4:
Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3choice Tff7b72= Tffa657inputTb4b4b4(Ta5d6fffTa5d6ff"Tffea00\nTffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffSelect template (1-6): Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3choice Tff7b72= Tffa657inputTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffSelect template (1-6): Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3choice Tff7b72in Tb4b4b4[Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff2Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff3Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff4Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff5Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff6Ta5d6ff"Tb4b4b4]Tb4b4b4:
Tff7b72return Te6edf3templatesTb4b4b4[Tffa657intTb4b4b4(Te6edf3choiceTb4b4b4) Tff7b72- T79c0ff1Tb4b4b4]
Te6edf3print_errorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid choice. Please enter a number between 1 and 6.Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffinteractive_createTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Interactive bot creation process."""
Te6edf3print_headerTb4b4b4(Ta5d6ff"Ta5d6ffCreate New BotTa5d6ff"Tb4b4b4)
Te6edf3bot_name Tff7b72= Te6edf3get_bot_nameTb4b4b4(Tb4b4b4)
Te6edf3template Tff7b72= Te6edf3get_template_choiceTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3output_path Tff7b72= Tb4b4b4(
Tffa657inputTb4b4b4(
Ta5d6fffTa5d6ff"Tffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffEnter output path (default: Tffd700{Te6edf3bot_nameTffd700}Ta5d6ff.py): Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72or Ta5d6fffTa5d6ff"Tffd700{Te6edf3bot_nameTffd700}Ta5d6ff.pyTa5d6ff"
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3output_path Tff7b72= Tb4b4b4(
Tffa657inputTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffEnter output path (default: Tffd700{Te6edf3bot_nameTffd700}Ta5d6ff.py): Ta5d6ff"Tb4b4b4) Tff7b72or Ta5d6fffTa5d6ff"Tffd700{Te6edf3bot_nameTffd700}Ta5d6ff.pyTa5d6ff"
Tb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3bot_path Tff7b72= Te6edf3create_from_templateTb4b4b4(Te6edf3templateTb4b4b4, Te6edf3output_pathTb4b4b4, Te6edf3bot_nameTb4b4b4)
Tff7b72if Te6edf3template Tff7b72== Ta5d6ff"Ta5d6ffbasicTa5d6ff"Tb4b4b4:
Te6edf3create_example_cogTb4b4b4(Te6edf3bot_pathTb4b4b4)
Te6edf3print_successTb4b4b4(Ta5d6ff"Ta5d6ffBot created successfully!Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"""
Ta5d6ffFiles created:
Ta5d6ff - Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff (main bot file)
Ta5d6ff - Tffd700{Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3bot_pathTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffcogsTa5d6ff"Tb4b4b4)Tffd700}
Ta5d6ff - __init__.py
Ta5d6ff - basic.py (example cog)

Ta5d6ffTo start your bot:
Ta5d6ff python Tffd700{Te6edf3bot_pathTffd700}

Ta5d6ffTo add admin rights, edit Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff and add your LXMF hash to the admins list.
Ta5d6ff Ta5d6ff"""Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3print_successTb4b4b4(Ta5d6ff"Ta5d6ffBot created successfully!Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"""
Ta5d6ffFiles created:
Ta5d6ff - Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff (main bot file)

Ta5d6ffTo start your bot:
Ta5d6ff python Tffd700{Te6edf3bot_pathTffd700}

Ta5d6ffTo add admin rights, edit Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff and add your LXMF hash to the admins list.
Ta5d6ff Ta5d6ff"""Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError creating bot: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffinteractive_runTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Interactive bot running process."""
Te6edf3print_headerTb4b4b4(Ta5d6ff"Ta5d6ffRun Template BotTa5d6ff"Tb4b4b4)
Te6edf3template Tff7b72= Te6edf3get_template_choiceTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3custom_name Tff7b72= Tffa657inputTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffEnter custom name (optional): Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3custom_name Tff7b72= Tffa657inputTb4b4b4(Ta5d6ff"Ta5d6ffEnter custom name (optional): Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3custom_nameTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3custom_name Tff7b72= Te6edf3validate_bot_nameTb4b4b4(Te6edf3custom_nameTb4b4b4)
Tff7b72except Tf85149ValueError Tff7b72as Te6edf3veTb4b4b4:
Te6edf3print_warningTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInvalid custom name provided. Using default. (Tffd700{Te6edf3veTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4)
Te6edf3custom_name Tff7b72= Tff7b72None

Tff7b72tryTb4b4b4:
Te6edf3template_map Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4: Te6edf3EchoBotTb4b4b4,
Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4: Te6edf3ReminderBotTb4b4b4,
Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4: Te6edf3NoteBotTb4b4b4,
Ta5d6ff"Ta5d6ffcogtestTa5d6ff"Tb4b4b4: Te6edf3CogTestBotTb4b4b4,
Ta5d6ff"Ta5d6ffrrcTa5d6ff"Tb4b4b4: Te6edf3RRCBotTb4b4b4,
Tb4b4b4}

Te6edf3BotClass Tff7b72= Te6edf3template_mapTb4b4b4[Te6edf3templateTb4b4b4]
Te6edf3print_headerTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffStarting Tffd700{Te6edf3templateTffd700}Ta5d6ff BotTa5d6ff"Tb4b4b4)
Te6edf3bot_instance Tff7b72= Te6edf3BotClassTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3custom_nameTb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3bot_instanceTb4b4b4, Ta5d6ff"Ta5d6ffbotTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3bot_instanceTff7b72.Td2a8ffbotTff7b72.Td2a8ffconfigTff7b72.Td2a8ffname Tff7b72= Te6edf3custom_name
Te6edf3bot_instanceTff7b72.Td2a8ffbotTff7b72.Td2a8ffname Tff7b72= Te6edf3custom_name
Tff7b72elseTb4b4b4:
Te6edf3bot_instanceTff7b72.Td2a8ffconfigTff7b72.Td2a8ffname Tff7b72= Te6edf3custom_name
Te6edf3bot_instanceTff7b72.Td2a8ffname Tff7b72= Te6edf3custom_name
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffRunning with custom name: Tffd700{Te6edf3custom_nameTffd700}Ta5d6ff"Tb4b4b4)

Te6edf3bot_instanceTff7b72.Td2a8ffrunTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError running template bot: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffinteractive_modeTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Run the CLI in interactive mode."""
Tff7b72while Tff7b72TrueTb4b4b4:
Te6edf3print_menuTb4b4b4(Tb4b4b4)
Te6edf3choice Tff7b72= Te6edf3get_user_choiceTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3choice Tff7b72== Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4:
Te6edf3interactive_createTb4b4b4(Tb4b4b4)
Tff7b72elif Te6edf3choice Tff7b72== Ta5d6ff"Ta5d6ff2Ta5d6ff"Tb4b4b4:
Te6edf3interactive_runTb4b4b4(Tb4b4b4)
Tff7b72elif Te6edf3choice Tff7b72== Ta5d6ff"Ta5d6ff3Ta5d6ff"Tb4b4b4:
Te6edf3print_successTb4b4b4(Ta5d6ff"Ta5d6ffGoodbye!Ta5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff0Tb4b4b4)

Tff7b72if Te6edf3ColorsTff7b72.Td2a8ffis_colors_supportedTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657inputTb4b4b4(Ta5d6fffTa5d6ff"Tffea00\nTffd700{Te6edf3ColorsTff7b72.Td2a8ffCYANTffd700}Ta5d6ffPress Enter to continue...Tffd700{Te6edf3ColorsTff7b72.Td2a8ffENDCTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657inputTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffPress Enter to continue...Ta5d6ff"Tb4b4b4)


Tff7b72def Td2a8ffsanitize_filenameTb4b4b4(Te6edf3filenameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Sanitizes the filename while preserving the extension.

Args:
filename: The filename to sanitize.

Returns:
Sanitized filename with proper extension.

"""
Te6edf3baseTb4b4b4, Te6edf3ext Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitextTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3filenameTb4b4b4)Tb4b4b4)
Te6edf3base Tff7b72= Te6edf3reTff7b72.Td2a8ffsubTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ff[^a-zA-Z0-9Ta5d6ff\Ta5d6ff-_]Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3baseTb4b4b4)

Tff7b72if Tff7b72not Te6edf3ext Tff7b72or Te6edf3ext Tff7b72!= Ta5d6ff"Ta5d6ff.pyTa5d6ff"Tb4b4b4:
Te6edf3ext Tff7b72= Ta5d6ff"Ta5d6ff.pyTa5d6ff"

Tff7b72return Ta5d6fffTa5d6ff"Tffd700{Te6edf3baseTffd700}Tffd700{Te6edf3extTffd700}Ta5d6ff"


Tff7b72def Td2a8ffvalidate_bot_nameTb4b4b4(Te6edf3nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Validates and sanitizes a bot name.

Args:
name: The proposed bot name.

Returns:
The sanitized bot name.

Raises:
ValueError: If the name is invalid.

"""
Tff7b72if Tff7b72not Te6edf3nameTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffBot name cannot be emptyTa5d6ff"Tb4b4b4)

Te6edf3sanitized Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3c Tff7b72for Te6edf3c Tff7b72in Te6edf3name Tff7b72if Te6edf3cTff7b72.Td2a8ffisalnumTb4b4b4(Tb4b4b4) Tff7b72or Te6edf3c Tff7b72in Ta5d6ff"Ta5d6ff -_Ta5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sanitizedTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffBot name must contain valid charactersTa5d6ff"Tb4b4b4)

Tff7b72return Te6edf3sanitized


Tff7b72def Td2a8ffcreate_bot_fileTb4b4b4(Te6edf3nameTb4b4b4: Tffa657strTb4b4b4, Te6edf3output_pathTb4b4b4: Tffa657strTb4b4b4, Te6edf3no_cogsTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Creates a new bot file from a template.

Args:
name: The name for the bot.
output_path: The desired output path.
no_cogs: Whether to disable cogs loading.

Returns:
The path to the created bot file.

Raises:
RuntimeError: If file creation fails.

"""
Tff7b72tryTb4b4b4:
Te6edf3name Tff7b72= Te6edf3validate_bot_nameTb4b4b4(Te6edf3nameTb4b4b4)

Te6edf3output_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3output_pathTb4b4b4)
Tff7b72if Te6edf3output_dirTb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3output_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72if Te6edf3output_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72or Te6edf3output_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Tffea00\\Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3base_name Tff7b72= Ta5d6ff"Ta5d6ffbot.pyTa5d6ff"
Te6edf3output_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3output_pathTb4b4b4, Te6edf3base_nameTb4b4b4)
Tff7b72elif Tff7b72not Te6edf3output_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.pyTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3output_path Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff.pyTa5d6ff"

Te6edf3safe_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3output_pathTb4b4b4)

Te6edf3template Tff7b72= Ta5d6fffTa5d6ff"""Ta5d6fffrom lxmfy import LXMFBot

Ta5d6ffbot = LXMFBot(
Ta5d6ff name=Ta5d6ff"Tffd700{Te6edf3nameTffd700}Ta5d6ff"Ta5d6ff,
Ta5d6ff announce=600,
Ta5d6ff announce_immediately=True,
Ta5d6ff admins=set(),
Ta5d6ff hot_reloading=False,
Ta5d6ff rate_limit=5,
Ta5d6ff cooldown=60,
Ta5d6ff max_warnings=3,
Ta5d6ff warning_timeout=300,
Ta5d6ff command_prefix=Ta5d6ff"Ta5d6ff/Ta5d6ff"Ta5d6ff,
Ta5d6ff cogs_dir=Ta5d6ff"Ta5d6ffcogsTa5d6ff"Ta5d6ff,
Ta5d6ff cogs_enabled=Tffd700{Tff7b72not Te6edf3no_cogsTffd700}Ta5d6ff,
Ta5d6ff permissions_enabled=False,
Ta5d6ff storage_type=Ta5d6ff"Ta5d6ffjsonTa5d6ff"Ta5d6ff,
Ta5d6ff storage_path=Ta5d6ff"Ta5d6ffdataTa5d6ff"Ta5d6ff,
Ta5d6ff first_message_enabled=True,
Ta5d6ff event_logging_enabled=True,
Ta5d6ff max_logged_events=1000,
Ta5d6ff event_middleware_enabled=True,
Ta5d6ff announce_enabled=True
Ta5d6ff)

Ta5d6ffif __name__ == Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Ta5d6ff:
Ta5d6ff bot.run()
Ta5d6ff"""
Tff7b72with Tffa657openTb4b4b4(Te6edf3safe_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3templateTb4b4b4)

Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3safe_pathTb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to create bot file: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4) Tff7b72from T7ee787e


Tff7b72def Td2a8ffcreate_example_cogTb4b4b4(Te6edf3bot_pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Creates an example cog and the necessary directory structure.

Args:
bot_path: The path to the bot file to determine the cogs location.

"""
Tff7b72tryTb4b4b4:
Te6edf3bot_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3bot_pathTb4b4b4)Tb4b4b4)
Te6edf3cogs_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_dirTb4b4b4, Ta5d6ff"Ta5d6ffcogsTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3cogs_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)

Te6edf3init_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3cogs_dirTb4b4b4, Ta5d6ff"Ta5d6ff__init__.pyTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3init_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)

Te6edf3template Tff7b72= Ta5d6ff"""Ta5d6fffrom lxmfy import Command

Ta5d6ffclass BasicCommands:
Ta5d6ff def __init__(self, bot):
Ta5d6ff self.bot = bot

Ta5d6ff @Command(name=Ta5d6ff"Ta5d6ffhelloTa5d6ff"Ta5d6ff, description=Ta5d6ff"Ta5d6ffSays helloTa5d6ff"Ta5d6ff)
Ta5d6ff async def hello(self, ctx):
Ta5d6ff ctx.reply(fTa5d6ff"Ta5d6ffHello Tffd700{ctx.sender}Ta5d6ff!Ta5d6ff"Ta5d6ff)

Ta5d6ff @Command(name=Ta5d6ff"Ta5d6ffaboutTa5d6ff"Ta5d6ff, description=Ta5d6ff"Ta5d6ffAbout this botTa5d6ff"Ta5d6ff)
Ta5d6ff async def about(self, ctx):
Ta5d6ff ctx.reply(Ta5d6ff"Ta5d6ffITa5d6ff'Ta5d6ffm a bot created with LXMFy!Ta5d6ff"Ta5d6ff)

Ta5d6ffdef setup(bot):
Ta5d6ff bot.add_cog(BasicCommands(bot))
Ta5d6ff"""
Te6edf3basic_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3cogs_dirTb4b4b4, Ta5d6ff"Ta5d6ffbasic.pyTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3basic_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3templateTb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to create example cog: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4) Tff7b72from T7ee787e


Tff7b72def Td2a8ffcreate_from_templateTb4b4b4(Te6edf3template_nameTb4b4b4: Tffa657strTb4b4b4, Te6edf3output_pathTb4b4b4: Tffa657strTb4b4b4, Te6edf3bot_nameTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Creates a bot from a template.

Args:
template_name: The name of the template to use.
output_path: The desired output path.
bot_name: The name for the bot.

Returns:
The path to the created bot file.

Raises:
ValueError: If the template is invalid.

"""
Tff7b72tryTb4b4b4:
Te6edf3name Tff7b72= Te6edf3validate_bot_nameTb4b4b4(Te6edf3bot_nameTb4b4b4)
Te6edf3output_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3output_pathTb4b4b4)
Tff7b72if Te6edf3output_dirTb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3output_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)

Tff7b72if Te6edf3output_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72or Te6edf3output_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Tffea00\\Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3base_name Tff7b72= Ta5d6ff"Ta5d6ffbot.pyTa5d6ff"
Te6edf3output_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3output_pathTb4b4b4, Te6edf3base_nameTb4b4b4)
Tff7b72elif Tff7b72not Te6edf3output_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.pyTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3output_path Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff.pyTa5d6ff"

Te6edf3safe_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3output_pathTb4b4b4)

Tff7b72if Te6edf3template_name Tff7b72== Ta5d6ff"Ta5d6ffbasicTa5d6ff"Tb4b4b4:
Tff7b72return Te6edf3create_bot_fileTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3safe_pathTb4b4b4)

Te6edf3template_map Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4: Te6edf3EchoBotTb4b4b4,
Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4: Te6edf3ReminderBotTb4b4b4,
Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4: Te6edf3NoteBotTb4b4b4,
Ta5d6ff"Ta5d6ffcogtestTa5d6ff"Tb4b4b4: Te6edf3CogTestBotTb4b4b4,
Ta5d6ff"Ta5d6ffrrcTa5d6ff"Tb4b4b4: Te6edf3RRCBotTb4b4b4,
Tb4b4b4}

Tff7b72if Te6edf3template_name Tff7b72not Tff7b72in Te6edf3template_mapTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffInvalid template: Tffd700{Te6edf3template_nameTffd700}Ta5d6ff. Available templates: basic, Tffd700{Ta5d6ff'Ta5d6ff, Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3template_mapTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3template Tff7b72= Ta5d6fffTa5d6ff"""Ta5d6fffrom lxmfy.templates import Tffd700{Te6edf3template_mapTb4b4b4[Te6edf3template_nameTb4b4b4]Tff7b72.Td2a8ff__name__Tffd700}

Ta5d6ffif __name__ == Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Ta5d6ff:
Ta5d6ff bot = Tffd700{Te6edf3template_mapTb4b4b4[Te6edf3template_nameTb4b4b4]Tff7b72.Td2a8ff__name__Tffd700}Ta5d6ff()
Ta5d6ff bot.bot.name = Ta5d6ff"Tffd700{Te6edf3nameTffd700}Ta5d6ff"Ta5d6ff # Set custom name
Ta5d6ff bot.run()
Ta5d6ff"""
Tff7b72with Tffa657openTb4b4b4(Te6edf3safe_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3templateTb4b4b4)

Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3safe_pathTb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to create bot from template: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4) Tff7b72from T7ee787e


Tff7b72def Td2a8ffis_safe_pathTb4b4b4(Te6edf3pathTb4b4b4: Tffa657strTb4b4b4, Te6edf3base_pathTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Checks if a path is safe and within the allowed directory.

Args:
path: The path to check.
base_path: The base path to check against. If None, all paths are considered safe.

Returns:
True if the path is safe, False otherwise.

"""
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3base_pathTb4b4b4:
Te6edf3base_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3base_pathTb4b4b4)
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72return Te6edf3pathTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3base_pathTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False


Tff7b72def Td2a8ffmainTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Main CLI entry point."""
Tff7b72tryTb4b4b4:
Te6edf3init_colorsTb4b4b4(Tb4b4b4)

Tff7b72if Tffa657lenTb4b4b4(Te6edf3sysTff7b72.Td2a8ffargvTb4b4b4) Tff7b72== T79c0ff1Tb4b4b4:
Te6edf3interactive_modeTb4b4b4(Tb4b4b4)
Tff7b72return

Te6edf3print_headerTb4b4b4(Ta5d6ff"Ta5d6ffLXMFy Bot FrameworkTa5d6ff"Tb4b4b4)

Te6edf3parser Tff7b72= Te6edf3argparseTff7b72.Td2a8ffArgumentParserTb4b4b4(
Te6edf3descriptionTff7b72=Ta5d6fffTa5d6ff"Ta5d6ffLXMFy Bot Tool (version Tffd700{Te6edf3__version__Tffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Te6edf3formatter_classTff7b72=Te6edf3argparseTff7b72.Td2a8ffRawDescriptionHelpFormatterTb4b4b4,
Te6edf3epilogTff7b72=Ta5d6ff"""
Ta5d6ffExamples:
Ta5d6ff lxmfy create # Create basic bot file Ta5d6ff'Ta5d6ffbot.pyTa5d6ff'
Ta5d6ff lxmfy create mybot # Create basic bot file Ta5d6ff'Ta5d6ffmybot.pyTa5d6ff'
Ta5d6ff lxmfy create --template echo mybot # Create echo bot file Ta5d6ff'Ta5d6ffmybot.pyTa5d6ff'
Ta5d6ff lxmfy create --template reminder bot # Create reminder bot file Ta5d6ff'Ta5d6ffbot.pyTa5d6ff'
Ta5d6ff lxmfy create --template note notes # Create note-taking bot file Ta5d6ff'Ta5d6ffnotes.pyTa5d6ff'
Ta5d6ff lxmfy create --template cogtest test # Create cog test bot file Ta5d6ff'Ta5d6fftest.pyTa5d6ff'

Ta5d6ff lxmfy run echo # Run the built-in echo bot
Ta5d6ff lxmfy run reminder --name Ta5d6ff"Ta5d6ffMyReminderTa5d6ff"Ta5d6ff # Run the reminder bot with a custom name
Ta5d6ff lxmfy run note # Run the built-in note bot
Ta5d6ff lxmfy run cogtest # Run the cog test bot

Ta5d6ff lxmfy signatures test # Test signature functionality
Ta5d6ff lxmfy signatures enable # Show how to enable signatures
Ta5d6ff lxmfy signatures disable # Show how to disable signatures
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4)

Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ffcommandTa5d6ff"Tb4b4b4,
Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff"Ta5d6ffcreateTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrunTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsignaturesTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffCreate a bot file, run a template bot, or manage signaturesTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4,
Te6edf3nargsTff7b72=Ta5d6ff"Ta5d6ff?Ta5d6ff"Tb4b4b4,
Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffName for Ta5d6ff'Ta5d6ffcreateTa5d6ff'Ta5d6ff (bot name/path) or Ta5d6ff'Ta5d6ffrunTa5d6ff'Ta5d6ff (template name: echo, reminder, note)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ffdirectoryTa5d6ff"Tb4b4b4,
Te6edf3nargsTff7b72=Ta5d6ff"Ta5d6ff?Ta5d6ff"Tb4b4b4,
Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffOutput directory for Ta5d6ff'Ta5d6ffcreateTa5d6ff'Ta5d6ff command (optional)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ff--templateTa5d6ff"Tb4b4b4,
Te6edf3choicesTff7b72=Tb4b4b4[Ta5d6ff"Ta5d6ffbasicTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcogtestTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrrcTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3defaultTff7b72=Ta5d6ff"Ta5d6ffbasicTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffBot template to use for Ta5d6ff'Ta5d6ffcreateTa5d6ff'Ta5d6ff command (default: basic)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ff--nameTa5d6ff"Tb4b4b4,
Te6edf3destTff7b72=Ta5d6ff"Ta5d6ffname_optTa5d6ff"Tb4b4b4,
Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffOptional custom name for the bot (used with Ta5d6ff'Ta5d6ffcreateTa5d6ff'Ta5d6ff or Ta5d6ff'Ta5d6ffrunTa5d6ff'Ta5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ff--outputTa5d6ff"Tb4b4b4,
Te6edf3defaultTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffOutput file path or directory for Ta5d6ff'Ta5d6ffcreateTa5d6ff'Ta5d6ff commandTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3parserTff7b72.Td2a8ffadd_argumentTb4b4b4(
Ta5d6ff"Ta5d6ff--no-cogsTa5d6ff"Tb4b4b4,
Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffstore_trueTa5d6ff"Tb4b4b4,
Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffDisable cogs loading for Ta5d6ff'Ta5d6ffcreateTa5d6ff'Ta5d6ff commandTa5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3args Tff7b72= Te6edf3parserTff7b72.Td2a8ffparse_argsTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8ffcommand Tff7b72== Ta5d6ff"Ta5d6ffcreateTa5d6ff"Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3bot_name Tff7b72= Te6edf3argsTff7b72.Td2a8ffname_opt Tff7b72or Te6edf3argsTff7b72.Td2a8ffname Tff7b72or Ta5d6ff"Ta5d6ffMyLXMFBotTa5d6ff"

Tff7b72if Te6edf3argsTff7b72.Td2a8ffoutputTb4b4b4:
Te6edf3output_path Tff7b72= Te6edf3argsTff7b72.Td2a8ffoutput
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffdirectoryTb4b4b4:
Te6edf3output_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3argsTff7b72.Td2a8ffdirectoryTb4b4b4, Ta5d6ff"Ta5d6ffbot.pyTa5d6ff"Tb4b4b4)
Tff7b72elif Te6edf3argsTff7b72.Td2a8ffnameTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72in Te6edf3argsTff7b72.Td2a8ffnameTb4b4b4:
Te6edf3output_path Tff7b72= Te6edf3argsTff7b72.Td2a8ffname
Tff7b72if Tff7b72not Te6edf3argsTff7b72.Td2a8ffname_optTb4b4b4:
Te6edf3bot_name Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitextTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3argsTff7b72.Td2a8ffnameTb4b4b4)Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3output_path Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3argsTff7b72.Td2a8ffnameTffd700}Ta5d6ff.pyTa5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3output_path Tff7b72= Ta5d6ff"Ta5d6ffbot.pyTa5d6ff"

Tff7b72tryTb4b4b4:
Te6edf3bot_name Tff7b72= Te6edf3validate_bot_nameTb4b4b4(Te6edf3bot_nameTb4b4b4)
Tff7b72except Tf85149ValueError Tff7b72as Te6edf3veTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInvalid bot name Ta5d6ff'Tffd700{Te6edf3bot_nameTffd700}Ta5d6ff'Ta5d6ff. Tffd700{Te6edf3veTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Te6edf3print_headerTb4b4b4(Ta5d6ff"Ta5d6ffCreating New BotTa5d6ff"Tb4b4b4)
Te6edf3bot_path Tff7b72= Te6edf3create_from_templateTb4b4b4(Te6edf3argsTff7b72.Td2a8fftemplateTb4b4b4, Te6edf3output_pathTb4b4b4, Te6edf3bot_nameTb4b4b4)

Tff7b72if Te6edf3argsTff7b72.Td2a8fftemplate Tff7b72== Ta5d6ff"Ta5d6ffbasicTa5d6ff"Tb4b4b4:
Te6edf3create_example_cogTb4b4b4(Te6edf3bot_pathTb4b4b4)
Te6edf3print_successTb4b4b4(Ta5d6ff"Ta5d6ffBot created successfully!Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"""
Ta5d6ffFiles created:
Ta5d6ff - Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff (main bot file)
Ta5d6ff - Tffd700{Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3bot_pathTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffcogsTa5d6ff"Tb4b4b4)Tffd700}
Ta5d6ff - __init__.py
Ta5d6ff - basic.py (example cog)

Ta5d6ffTo start your bot:
Ta5d6ff python Tffd700{Te6edf3bot_pathTffd700}

Ta5d6ffTo add admin rights, edit Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff and add your LXMF hash to the admins list.
Ta5d6ff Ta5d6ff"""Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3print_successTb4b4b4(Ta5d6ff"Ta5d6ffBot created successfully!Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"""
Ta5d6ffFiles created:
Ta5d6ff - Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff (main bot file)

Ta5d6ffTo start your bot:
Ta5d6ff python Tffd700{Te6edf3bot_pathTffd700}

Ta5d6ffTo add admin rights, edit Tffd700{Te6edf3bot_pathTffd700}Ta5d6ff and add your LXMF hash to the admins list.
Ta5d6ff Ta5d6ff"""Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError creating bot: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72elif Te6edf3argsTff7b72.Td2a8ffcommand Tff7b72== Ta5d6ff"Ta5d6ffrunTa5d6ff"Tb4b4b4:
Te6edf3template_name Tff7b72= Te6edf3argsTff7b72.Td2a8ffname
Tff7b72if Tff7b72not Te6edf3template_nameTb4b4b4:
Te6edf3print_errorTb4b4b4(
Ta5d6ff"Ta5d6ffPlease specify a template name to run (echo, reminder, note, cogtest, rrc)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Te6edf3template_map Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4: Te6edf3EchoBotTb4b4b4,
Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4: Te6edf3ReminderBotTb4b4b4,
Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4: Te6edf3NoteBotTb4b4b4,
Ta5d6ff"Ta5d6ffcogtestTa5d6ff"Tb4b4b4: Te6edf3CogTestBotTb4b4b4,
Ta5d6ff"Ta5d6ffrrcTa5d6ff"Tb4b4b4: Te6edf3RRCBotTb4b4b4,
Tb4b4b4}

Tff7b72if Te6edf3template_name Tff7b72not Tff7b72in Te6edf3template_mapTb4b4b4:
Te6edf3print_errorTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffInvalid template name Ta5d6ff'Tffd700{Te6edf3template_nameTffd700}Ta5d6ff'Ta5d6ff. Choose from: Tffd700{Ta5d6ff'Ta5d6ff, Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3template_mapTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3BotClass Tff7b72= Te6edf3template_mapTb4b4b4[Te6edf3template_nameTb4b4b4]
Te6edf3print_headerTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffStarting Tffd700{Te6edf3template_nameTffd700}Ta5d6ff BotTa5d6ff"Tb4b4b4)
Te6edf3bot_instance Tff7b72= Te6edf3BotClassTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3template_name Tff7b72== Ta5d6ff"Ta5d6ffrrcTa5d6ff" Tff7b72and Tffa657hasattrTb4b4b4(Te6edf3bot_instanceTb4b4b4, Ta5d6ff"Ta5d6ffbotTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3hubs Tff7b72= Te6edf3bot_instanceTff7b72.Td2a8ffbotTff7b72.Td2a8ffconfigTff7b72.Td2a8ffrrc_hubs Tff7b72or Tb4b4b4[Tb4b4b4]
Te6edf3rooms Tff7b72= Te6edf3bot_instanceTff7b72.Td2a8ffbotTff7b72.Td2a8ffconfigTff7b72.Td2a8ffrrc_rooms Tff7b72or Tb4b4b4[Tb4b4b4]
Te6edf3rns_dir Tff7b72= Tffa657getattrTb4b4b4(Te6edf3bot_instanceTff7b72.Td2a8ffbotTb4b4b4, Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3print_infoTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffRRC hubs: Tffd700{Ta5d6ff'Ta5d6ff, Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3hubsTb4b4b4) Tff7b72if Te6edf3hubs Tff7b72else Ta5d6ff'Ta5d6ff(none)Ta5d6ff'Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3print_infoTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffRRC rooms: Tffd700{Ta5d6ff'Ta5d6ff, Ta5d6ff'Tff7b72.Td2a8ffjoinTb4b4b4(Ta5d6ff'Ta5d6ff#Ta5d6ff' Tff7b72+ Te6edf3r Tff7b72for Te6edf3r Tff7b72in Te6edf3roomsTb4b4b4) Tff7b72if Te6edf3rooms Tff7b72else Ta5d6ff'Ta5d6ff(none)Ta5d6ff'Tffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffReticulum config: Tffd700{Te6edf3rns_dir Tff7b72or Ta5d6ff'Ta5d6ff(default)Ta5d6ff'Tffd700}Ta5d6ff"Tb4b4b4)

Te6edf3custom_name Tff7b72= Te6edf3argsTff7b72.Td2a8ffname_opt
Tff7b72if Te6edf3custom_nameTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3validated_name Tff7b72= Te6edf3validate_bot_nameTb4b4b4(Te6edf3custom_nameTb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3bot_instanceTb4b4b4, Ta5d6ff"Ta5d6ffbotTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3bot_instanceTff7b72.Td2a8ffbotTff7b72.Td2a8ffconfigTff7b72.Td2a8ffname Tff7b72= Te6edf3validated_name
Te6edf3bot_instanceTff7b72.Td2a8ffbotTff7b72.Td2a8ffname Tff7b72= Te6edf3validated_name
Tff7b72elseTb4b4b4:
Te6edf3bot_instanceTff7b72.Td2a8ffconfigTff7b72.Td2a8ffname Tff7b72= Te6edf3validated_name
Te6edf3bot_instanceTff7b72.Td2a8ffname Tff7b72= Te6edf3validated_name
Te6edf3print_infoTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffRunning with custom name: Tffd700{Te6edf3validated_nameTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72except Tf85149ValueError Tff7b72as Te6edf3veTb4b4b4:
Te6edf3print_warningTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffInvalid custom name Ta5d6ff'Tffd700{Te6edf3custom_nameTffd700}Ta5d6ff'Ta5d6ff provided. Using default. (Tffd700{Te6edf3veTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3bot_instanceTff7b72.Td2a8ffrunTb4b4b4(Tb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError running template bot Ta5d6ff'Tffd700{Te6edf3template_nameTffd700}Ta5d6ff'Ta5d6ff: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72elif Te6edf3argsTff7b72.Td2a8ffcommand Tff7b72== Ta5d6ff"Ta5d6ffsignaturesTa5d6ff"Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3print_headerTb4b4b4(Ta5d6ff"Ta5d6ffSignature ManagementTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3argsTff7b72.Td2a8ffnameTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6ff"Ta5d6ffPlease specify a subcommand: test, enable, disableTa5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ffUsage: lxmfy signatures <subcommand>Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(
Ta5d6ff"Ta5d6ff test - Test signature verification with sample dataTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ff enable - Show how to enable signature verificationTa5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(
Ta5d6ff"Ta5d6ff disable - Show how to disable signature verificationTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Te6edf3subcommand Tff7b72= Te6edf3argsTff7b72.Td2a8ffname

Tff7b72if Te6edf3subcommand Tff7b72== Ta5d6ff"Ta5d6fftestTa5d6ff"Tb4b4b4:
Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ffTesting signature functionality...Ta5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72import T7ee787RNS

Tff7b72from T7ee787lxmfyT7ee787.T7ee787signatures Tff7b72import Te6edf3FIELD_SIGNATURETb4b4b4, Te6edf3SignatureManager

Te6edf3identity1 Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Tb4b4b4)
Te6edf3identity2 Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Tb4b4b4)

Tff7b72class T56d364MockBotTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpermissions Tff7b72= Te6edf3MockPermissionsTb4b4b4(Tb4b4b4)

Tff7b72class T56d364MockPermissionsTb4b4b4:
Tf0883e@staticmethod
Tff7b72def Td2a8ffhas_permissionTb4b4b4(Te6edf3userTb4b4b4, Te6edf3permTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False T8b949e# No bypass for testing

Te6edf3bot Tff7b72= Te6edf3MockBotTb4b4b4(Tb4b4b4)
Te6edf3sig_manager Tff7b72= Te6edf3SignatureManagerTb4b4b4(
Te6edf3botTb4b4b4,
Te6edf3verification_enabledTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3require_signaturesTff7b72=Tff7b72FalseTb4b4b4,
Tb4b4b4)

Tff7b72class T56d364MockMessageTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3source_hashTb4b4b4,
Te6edf3dest_hashTb4b4b4,
Te6edf3contentTb4b4b4,
Te6edf3titleTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3fieldsTff7b72=Tff7b72NoneTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffsource_hash Tff7b72= Te6edf3source_hash
Tff7b72selfTff7b72.Td2a8ffdestination_hash Tff7b72= Te6edf3dest_hash
Tff7b72selfTff7b72.Td2a8ffcontent Tff7b72= Te6edf3content
Tff7b72selfTff7b72.Td2a8fftitle Tff7b72= Te6edf3title Tff7b72or Ta5d6ffbTa5d6ff"Ta5d6ffTestTa5d6ff"
Tff7b72selfTff7b72.Td2a8fffields Tff7b72= Te6edf3fields Tff7b72or Tb4b4b4{Tb4b4b4}

Te6edf3test_msg Tff7b72= Te6edf3MockMessageTb4b4b4(
Te6edf3identity1Tff7b72.Td2a8ffhashTb4b4b4,
Te6edf3identity2Tff7b72.Td2a8ffhashTb4b4b4,
Ta5d6ffbTa5d6ff"Ta5d6ffHello, World!Ta5d6ff"Tb4b4b4,
Ta5d6ffbTa5d6ff"Ta5d6ffTest MessageTa5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3signature Tff7b72= Te6edf3sig_managerTff7b72.Td2a8ffsign_messageTb4b4b4(Te6edf3test_msgTb4b4b4, Te6edf3identity1Tb4b4b4)
Te6edf3print_successTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffOK Message signed successfully (signature length: Tffd700{Tffa657lenTb4b4b4(Te6edf3signatureTb4b4b4)Tffd700}Ta5d6ff bytes)Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Te6edf3test_msgTff7b72.Td2a8fffieldsTb4b4b4[Te6edf3FIELD_SIGNATURETb4b4b4] Tff7b72= Te6edf3signature
Te6edf3is_valid Tff7b72= Te6edf3sig_managerTff7b72.Td2a8ffverify_message_signatureTb4b4b4(
Te6edf3test_msgTb4b4b4,
Te6edf3signatureTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffhexrepTb4b4b4(Te6edf3identity1Tff7b72.Td2a8ffhashTb4b4b4, Te6edf3delimitTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3is_validTb4b4b4:
Te6edf3print_successTb4b4b4(Ta5d6ff"Ta5d6ffOK Signature verification successfulTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6ff"Ta5d6ffFAIL Signature verification failedTa5d6ff"Tb4b4b4)

Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ffSignature test completed successfully!Ta5d6ff"Tb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffSignature test failed: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ffThis may be due to RNS initialization requirementsTa5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72elif Te6edf3subcommand Tff7b72== Ta5d6ff"Ta5d6ffenableTa5d6ff"Tb4b4b4:
Te6edf3print_infoTb4b4b4(
Ta5d6ff"Ta5d6ffTo enable signature verification in your bot, add these parameters to your LXMFBot constructor:Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(
Ta5d6ff"Ta5d6ffsignature_verification_enabled=True, # Enable signature checkingTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(
Ta5d6ff"Ta5d6ffrequire_message_signatures=False, # Set to True to reject unsigned messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrequire_stamps=False, # Set to True to reject invalid stampsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrequest_unknown_identities=False, # Set to True to request unknown keysTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ffExample:Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffbot = LXMFBot(Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff name=Ta5d6ff'Ta5d6ffMyBotTa5d6ff'Ta5d6ff,Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff signature_verification_enabled=True,Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff require_message_signatures=False,Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff require_stamps=FalseTa5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff)Ta5d6ff"Tb4b4b4)

Tff7b72elif Te6edf3subcommand Tff7b72== Ta5d6ff"Ta5d6ffdisableTa5d6ff"Tb4b4b4:
Te6edf3print_infoTb4b4b4(
Ta5d6ff"Ta5d6ffSignature verification is disabled by default. To explicitly disable:Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(
Ta5d6ff"Ta5d6ffsignature_verification_enabled=False, # Disable signature checkingTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(
Ta5d6ff"Ta5d6ffrequire_message_signatures=False, # Not required when disabledTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrequire_stamps=False, # Set to True to still require stampsTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(Tb4b4b4)
Te6edf3print_infoTb4b4b4(
Ta5d6ff"Ta5d6ffOr simply omit these parameters (they default to False)Ta5d6ff"Tb4b4b4,
Tb4b4b4)

Tff7b72elseTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffUnknown subcommand: Tffd700{Te6edf3subcommandTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3print_infoTb4b4b4(Ta5d6ff"Ta5d6ffAvailable subcommands: test, enable, disableTa5d6ff"Tb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3print_errorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError in signatures command: Tffd700{Te6edf3eTffd700!s}Ta5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff1Tb4b4b4)

Tff7b72except Tf85149KeyboardInterruptTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffExiting...Ta5d6ff"Tb4b4b4)
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(T79c0ff0Tb4b4b4)


Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Te6edf3mainTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────